//package com.dfs.parent.gateway.loadbalancer;
//
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.collection.CollectionUtil;
//import cn.hutool.core.convert.Convert;
//import cn.hutool.core.lang.TypeReference;
//import cn.hutool.core.util.StrUtil;
//import com.dfs.parent.common.core.constant.GrayConstant;
//import com.dfs.parent.common.core.constant.TokenConstant;
//import com.dfs.parent.common.core.context.GrayContextHolder;
//import com.dfs.parent.gateway.props.GrayAppointProperties;
//import com.dfs.parent.gateway.props.GrayBatchProperties;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.ObjectProvider;
//import org.springframework.cloud.client.ServiceInstance;
//import org.springframework.cloud.client.loadbalancer.*;
//import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
//import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
//import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
//import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
//import org.springframework.http.HttpHeaders;
//import reactor.core.publisher.Mono;
//
//import java.util.List;
//import java.util.Random;
//import java.util.concurrent.atomic.AtomicInteger;
//import java.util.stream.Collectors;
//
///**
// * @Description TODO
// * @Author dahong
// * @Date 2024/2/18 10:31
// */
//@Slf4j
//public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
//    /**
//     * 用于获取 serviceId 对应的服务实例的列表
//     */
//    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
//    /**
//     * 需要获取的服务实例名
//     *
//     * 暂时用于打印 logger 日志
//     */
//    private String serviceId;
//    private GrayBatchProperties grayBatchProperties;
//    private GrayAppointProperties grayAppointProperties;
//    private AtomicInteger position;
//
//    public GrayLoadBalancer( ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,String serviceId
//            ,GrayBatchProperties grayBatchProperties,GrayAppointProperties grayAppointProperties) {
//        this(new Random().nextInt(1000),serviceInstanceListSupplierProvider,serviceId,grayBatchProperties,grayAppointProperties);
//    }
//
//    public GrayLoadBalancer(int seedPosition,ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
//                                  String serviceId,GrayBatchProperties grayBatchProperties, GrayAppointProperties grayAppointProperties) {
//        this.serviceId = serviceId;
//        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
//        this.position = new AtomicInteger(seedPosition);
//        this.grayBatchProperties = grayBatchProperties;
//        this.grayAppointProperties = grayAppointProperties;
//    }
//
//    @Override
//    public Mono<Response<ServiceInstance>> choose(Request request) {
//        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
//                .getIfAvailable(NoopServiceInstanceListSupplier::new);
//        log.info("grayAppointProperties enabled value={},grayBatchProperties userSharding value={}",grayAppointProperties.getEnabled(),grayBatchProperties.getUserSharding());
//        return supplier.get(request).next()
//                .map(serviceInstances -> processInstanceResponse(supplier, serviceInstances, request));
//    }
//    private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,
//                                                              List<ServiceInstance> serviceInstances,Request request) {
//        Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances, request);
//        if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
//            ((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
//        }
//        return serviceInstanceResponse;
//    }
//    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, Request request) {
//        if (CollUtil.isEmpty(instances)) {
//            if (log.isWarnEnabled()) {
//                log.warn("No servers available for service: " + serviceId);
//            }
//            return new EmptyResponse();
//        }
//        //获取是否灰度用户
//      // String isGray = getGrayUser(request);
//        String isGray = "true";
//
//        // Do not move position when there is only 1 instance, especially some suppliers
//        // have already filtered instances
//        if (instances.size() == 1) {
//            return new DefaultResponse(instances.get(0));
//        }
//
//        // 获取ServiceInstance列表
//        instances = getInstances(instances, isGray);
//
//        if (instances.size() == 1) {
//            return new DefaultResponse(instances.get(0));
//        }
//
//        // Ignore the sign bit, this allows pos to loop sequentially from 0 to
//        // Integer.MAX_VALUE
//        int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
//
//        ServiceInstance instance = instances.get(pos % instances.size());
//
//        return new DefaultResponse(instance);
//    }
//    private String getGrayUser(Request request){
//        DefaultRequest<RequestDataContext> defaultRequest = Convert.convert(
//                new TypeReference<DefaultRequest<RequestDataContext>>() {
//                }, request);
//        RequestDataContext dataContext = defaultRequest.getContext();
//        RequestData requestData = dataContext.getClientRequest();
//        HttpHeaders headers = requestData.getHeaders();
//        /**
//         * 获取用户UserId 判断是否灰度用户
//         * 判断是否根据特定用户信息，或者ip返回值
//         * 判断是否根据用户逻辑返回信息
//         *
//         * 不是灰度用户，找没有服务元数据的灰度标志，找不到选择全部
//         * 灰度用户，找有服务元数据的灰度标志，找不到选择全部
//         */
//        String isGray = GrayConstant.GRAY_TAG_VALUE_FALSE;
//        Long userId = Long.valueOf(headers.getFirst(TokenConstant.DFS_TOKEN_USER_ID));
//        if(GrayConstant.GRAY_TAG_VALUE_TRUE.equals(grayAppointProperties.getEnabled())){
//            if(grayAppointProperties.getUserIds().contains(userId)){
//                isGray = GrayConstant.GRAY_TAG_VALUE_TRUE;
//                GrayContextHolder.setGrayTag(GrayConstant.GRAY_TAG_VALUE_TRUE);
//            }
//        }else if(GrayConstant.GRAY_TAG_VALUE_TRUE.equals(grayBatchProperties.getEnabled())){
//            if(grayBatchProperties.getUserIdRemainder() == userId % grayBatchProperties.getUserSharding()){
//                isGray = GrayConstant.GRAY_TAG_VALUE_TRUE;
//                GrayContextHolder.setGrayTag(GrayConstant.GRAY_TAG_VALUE_TRUE);
//            }
//        }
//        return isGray;
//    }
//    private List<ServiceInstance> getInstances(List<ServiceInstance> instances, String isGray) {
//
//        // 灰度标记不为空并且标记为true, 筛选ServiceInstance
//        List<ServiceInstance> chooseInstances = instances.stream()
//                .filter(instance -> StrUtil.isNotEmpty(instance.getMetadata().get(GrayConstant.GRAY_TAG))
//                 && GrayConstant.GRAY_TAG_VALUE_TRUE.equals(instance.getMetadata().get(GrayConstant.GRAY_TAG)))
//                .collect(Collectors.toList());
//        if (GrayConstant.GRAY_TAG_VALUE_TRUE.equals(isGray)) {
//            if(CollUtil.isEmpty(chooseInstances)){
//                return instances;
//            }
//            return chooseInstances;
//        } else {
//            instances.removeAll(chooseInstances);
//            return instances;
//        }
//    }
//
//}
